package com.remoteapp.activities;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Switch;
import android.widget.Toast;

import com.remoteapp.config.AppConfig;
import com.remoteapp.connection.ConnectionHandler;
import com.remoteapp.main.R;
import com.remoteapp.networking.ClientReceiver;

/**
 * @author Jonas Spitzenpfeil
 * 
 */
public class MainActivity extends Activity implements OnCheckedChangeListener,
		ClientReceiver {
	public static final int SWITCH_COUNT = 8;

	/** CheckBox to enable or disable LED */
	Switch[] switchGPIO = new Switch[SWITCH_COUNT];

	private String lastResult = "";

	/** Notify switch press with OnCheckedChange event or not */
	private boolean notifySwitch = true;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// Switch for LED properties
		switchGPIO[0] = (Switch) findViewById(R.id.switchGPIO00);
		switchGPIO[1] = (Switch) findViewById(R.id.switchGPIO01);
		switchGPIO[2] = (Switch) findViewById(R.id.switchGPIO02);
		switchGPIO[3] = (Switch) findViewById(R.id.switchGPIO03);
		switchGPIO[4] = (Switch) findViewById(R.id.switchGPIO04);
		switchGPIO[5] = (Switch) findViewById(R.id.switchGPIO05);
		switchGPIO[6] = (Switch) findViewById(R.id.switchGPIO06);
		switchGPIO[7] = (Switch) findViewById(R.id.switchGPIO07);

		for (int n = 0; n < SWITCH_COUNT; n++) {
			switchGPIO[n].setOnCheckedChangeListener(this);
		}

		ConnectionHandler.setClientReceiver(this);
		applyConfig();
	}

	/**
	 * Setzt alle Werte aus der Konfiguration
	 */
	private void applyConfig() {
		try {
			AppConfig.setMainActivity(this);

			// Load configuration and try to connect
			if (AppConfig.loadConfig()) {

				if (AppConfig.AUTO_CONNECT) {
					ConnectionHandler.connectClientToServer(
							AppConfig.IP_ADDRESS, AppConfig.PORT);

					Toast.makeText(getApplicationContext(),
							"Connected to " + AppConfig.IP_ADDRESS,
							Toast.LENGTH_SHORT).show();
				}
			}
		} catch (Exception e) {
			Toast.makeText(getApplicationContext(), e.getMessage(),
					Toast.LENGTH_LONG).show();
		}

		refreshSwitches();
	}

	/**
	 * Erneuert die Namen der GPIO Switches
	 */
	public void refreshSwitches() {
		// Set configured text for each switch
		for (int n = 0; n < SWITCH_COUNT; n++) {
			switchGPIO[n].setText(AppConfig.GPIO_NAMES[n]);
		}
	}

	@Override
	protected void onDestroy() {
		try {
			// Disconnect the client when application is shutting down
			ConnectionHandler.disconnectClientFromServer();

		} catch (Exception e) {
			Toast.makeText(getApplicationContext(), e.getMessage(),
					Toast.LENGTH_LONG).show();
		}

		super.onDestroy();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {

		// Connection Settings
		case R.id.connection_settings:
			Intent conn = new Intent(MainActivity.this,
					ConnectionActivity.class);
			MainActivity.this.startActivity(conn);
			break;

		// View Settings
		case R.id.view_settings:
			Intent view = new Intent(MainActivity.this, ViewActivity.class);
			MainActivity.this.startActivity(view);
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
		if (!notifySwitch) {
			return;
		}

		try {
			// Check which Switch has changed and send the event of the correct
			// switch
			for (int i = 0; i < switchGPIO.length; i++) {

				if (switchGPIO[i] == buttonView) {
					boolean b = AppConfig.INVERT_GPIOS[i];
					String command = "PIN " + i + " "
							+ ((isChecked != b) ? 1 : 0);
					ConnectionHandler.sendCommand(command);
				}
			}

		} catch (Exception e) {
			Toast.makeText(getApplicationContext(), e.getMessage(),
					Toast.LENGTH_LONG).show();
		}
	}

	@Override
	public void connectedToServer(String ipAddress) {
		try {
			// Notify connection
			Toast.makeText(getApplicationContext(),
					"Connected to " + ipAddress, Toast.LENGTH_SHORT).show();

			ConnectionHandler.sendCommand("PINS ?");

		} catch (Exception e) {
			Toast.makeText(getApplicationContext(), e.getMessage(),
					Toast.LENGTH_LONG).show();
		}
	}

	@Override
	public void disconnectedFromServer(String ipAddress) {
		// Notify connection
		Toast.makeText(getApplicationContext(),
				"Disconnected from " + ipAddress, Toast.LENGTH_SHORT).show();
	}

	@Override
	public void lostConnection(String ipAddress) {
		// Notify connection
		Toast.makeText(getApplicationContext(),
				"Lost connection to " + ipAddress, Toast.LENGTH_SHORT).show();
	}

	@Override
	public void lineReceived(String line) {
		try {
			if (line.startsWith("PINS")) {
				lastResult = line;

				MainActivity.this.runOnUiThread(new Runnable() {

					@Override
					public void run() {
						String[] s = lastResult.split(" ");
						if (s.length < 2) {
							return;
						}

						int states = Integer.parseInt(s[1]);
						notifySwitch = false;

						// Setze die States der Pins
						for (int n = 0; n < SWITCH_COUNT; n++) {
							boolean b = (states & (1 << n)) > 0;
							boolean inv = AppConfig.INVERT_GPIOS[n];
							switchGPIO[n].setChecked(b != inv);
						}

						notifySwitch = true;
						lastResult = "";
					}
				});
			}
		} catch (Exception e) {
			Toast.makeText(getApplicationContext(), e.getMessage(),
					Toast.LENGTH_LONG).show();
		}
	}

}
